module Main where

import System.IO.Unsafe (unsafePerformIO)
import Test.HUnit

import Hsrb.Eval

suite :: [Test]
suite = [
    "nil" ~: testNil,
    "int" ~: testInt,
    "integer" ~: testInteger,
    "double" ~: testDouble,
    "string" ~: testString]

testNil = [
    RbNil ~=? u (rbEval "nil")]

u  = unsafePerformIO

testString = [
    "2" ~=? du (rbEval "hoge = 2;\"#{hoge}\""),
    "100" ~=? du (rbEval "100.to_s"),
    "hoge" ~=? du (rbEval "'h'+'o'+'g'+'e'"),
    "hoge" ~=? du (rbEval "'hoge'"),
    "hogepiyo" ~=? du (rbEval "'hogefugapiyo'.gsub(/fuga/,'')"),
    "hogefugapiyo" ~=? du (rbEval "'hogefugapiyo'.gsub(/xxxx/,'')"),
    "hogefugapiyo" ~=? du (rbEval "%Q!hogefugapiyo!"),
    "hoge#{fuga}piyo" ~=? du (rbEval "fuga = 2;'hoge#{fuga}piyo'")]
  where d (RbString str) = str
        du = d . u
        
testInt = [
    2 ~=? du (rbEval "2"),
    0 ~=? du (rbEval "0"),
    -1 ~=? du (rbEval "-1"),
    1073741823 ~=? du (rbEval "0b111111111111111111111111111111"),
    -1073741824 ~=? du (rbEval "~0b111111111111111111111111111111")
    ]
  where d (RbInt val) = val
        du = d . u

testInteger = [
    1073741824 ~=? du (rbEval "0b111111111111111111111111111111 + 1"),
    2147483647 ~=? du (rbEval "0b1111111111111111111111111111111"),
    2147483648 ~=? du (rbEval "0b1111111111111111111111111111111 + 1"),
    4294967295 ~=? du (rbEval "0b11111111111111111111111111111111"),
    -1073741825 ~=? du (rbEval "~0b111111111111111111111111111111 - 1"),
    -2147483648 ~=? du (rbEval "~0b1111111111111111111111111111111"),
    -2147483649 ~=? du (rbEval "~0b1111111111111111111111111111111 - 1"),
    -4294967296 ~=? du (rbEval "~0b11111111111111111111111111111111"),
    4294967295^10 ~=? du (rbEval "(0b11111111111111111111111111111111)**10"),
    negate (4294967295^100) ~=? du (rbEval "(0b11111111111111111111111111111111)**100 * -1")
    ]
  where d (RbInteger val) = val
        du = d . u

testDouble = [
    0.1 ~=? du (rbEval "0.1"),
    0.00000000000000000000000001 ~=? du (rbEval "0.00000000000000000000000001"),
    True ~=? isNaN (du (rbEval "0.0/0.0")),
    True ~=? isInfinite (du (rbEval "1.0/0.0")),
    True ~=? isInfinite (du (rbEval "-1.0/0.0"))
    ]
  where d (RbDouble val) = val
        du = d . u

main = runTestTT $ test suite
